// 状态变量
const state = {
    targets: {}, // 当前目标数据
    tracking: false, // 是否正在记录轨迹
    tracks: {}, // 轨迹数据
    selectedTargets: new Set(), // 选中的目标
    scale: 100, // 缩放比例，1个单位=100像素
    offsetX: 0, // X轴偏移
    offsetY: 0, // Y轴偏移
    isDragging: false, // 是否正在拖动
    lastX: 0, // 上次鼠标X坐标
    lastY: 0, // 上次鼠标Y坐标
    isPinching: false, // 是否正在捏合缩放
    lastDistance: 0, // 上次捏合距离
    pinchCenterX: 0, // 捏合中心X坐标
    pinchCenterY: 0, // 捏合中心Y坐标
    range: 50, // 默认显示50米范围
    autoRange: false, // 是否自动适应范围
};

// MODE对应的颜色
const modeColors = {
    'NON': 'bg-red-500',
    'GPS': 'bg-yellow-500',
    'RTK': 'bg-green-500',
    'default': 'bg-orange-500'
};

// DOM元素
let grid, axes, targetsContainer, trackingLinesContainer, targetsInfo;
let startRecordBtn, clearRecordBtn, saveRecordBtn, coordinateContainer, selectAllCheckbox, rangeSelect;

// 初始化
function init() {
    // 获取DOM元素
    grid = document.getElementById('grid');
    axes = document.getElementById('axes');
    targetsContainer = document.getElementById('targets-container');
    trackingLinesContainer = document.getElementById('tracking-lines-container');
    targetsInfo = document.getElementById('targets-info');
    startRecordBtn = document.getElementById('startRecord');
    clearRecordBtn = document.getElementById('clearRecord');
    saveRecordBtn = document.getElementById('saveRecord');
    coordinateContainer = document.getElementById('coordinate-container');
    selectAllCheckbox = document.getElementById('selectAll');
    rangeSelect = document.getElementById('rangeSelect');

    // 设置网格背景大小
    updateGrid();
    renderAxes();

    // 绑定事件
    bindEvents();

    // 开始轮询数据
    startPolling();
}

// 开始轮询数据
function startPolling() {
    if (state.intervalId) clearInterval(state.intervalId);

    state.intervalId = setInterval(fetchTargets, 300);
    fetchTargets(); // 立即获取一次数据
}

// 获取目标数据
async function fetchTargets() {
    try {
        const response = await fetch('/targets');
        if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);

        const data = await response.json();
        updateTargets(data.targets);
    } catch (error) {
        console.error('获取目标数据失败:', error);
        // 显示错误信息
        targetsInfo.innerHTML = `
            <div class="text-center text-red-500">
                <i class="fa fa-exclamation-triangle mr-2"></i>无法获取目标数据
            </div>
        `;
    }
}

// 更新目标数据
function updateTargets(newTargets) {
    const updatedTargets = {};

    newTargets.forEach(target => {
        const { IP, MODE, RSSI, LLA, XYZ, DELAY } = target;
        const [longitude, latitude, altitude] = LLA;
        const [x, y, z] = XYZ;

        // 计算距离原点的距离
        const distance = Math.sqrt(x*x + y*y + z*z);

        // 保存目标数据
        updatedTargets[IP] = {
            ip: IP,
            mode: MODE,
            rssi: RSSI,
            lla: { longitude, latitude, altitude },
            xyz: { x, y, z },
            delay: DELAY,
            distance,
            timestamp: Date.now()
        };

        // 如果正在记录，添加轨迹点
        if (state.tracking) {
            if (!state.tracks[IP]) state.tracks[IP] = [];
            state.tracks[IP].push({
                x, y, z,
                rssi: RSSI,
                mode: MODE,
                lla: { longitude, latitude, altitude },
                timestamp: Date.now()
            });
        }
    });

    state.targets = updatedTargets;

    // 如果是自动模式，调整范围以适应所有目标
    if (state.autoRange && Object.keys(state.targets).length > 0) {
        adjustRangeToFitTargets();
    }

    renderTargets();
    renderTargetsInfo();
    renderTrackingLines();
}

// 调整范围以适应所有目标
function adjustRangeToFitTargets() {
    if (Object.keys(state.targets).length === 0) return;

    // 找到最远的目标
    let maxDistance = 0;
    Object.values(state.targets).forEach(target => {
        maxDistance = Math.max(maxDistance, target.distance);
    });

    // 稍微扩大一点范围以便更好地显示
    const adjustedRange = Math.min(100, Math.max(1, Math.ceil(maxDistance * 1.2)));

    if (adjustedRange !== state.range) {
        state.range = adjustedRange;
        // 更新下拉选择框，但不触发事件
        const event = rangeSelect.onchange;
        rangeSelect.onchange = null;
        rangeSelect.value = adjustedRange;
        rangeSelect.onchange = event;

        // 重新计算缩放比例
        calculateScaleFromRange();
    }
}

// 根据选择的范围计算缩放比例
function calculateScaleFromRange() {
    const containerRect = coordinateContainer.getBoundingClientRect();
    // 计算使所选范围刚好适应容器的缩放比例
    // 留出10%的边距
    const availableWidth = containerRect.width * 0.9;
    const availableHeight = containerRect.height * 0.9;

    // 基于宽度和高度计算合适的缩放比例
    const scaleByWidth = availableWidth / (state.range * 2);
    const scaleByHeight = availableHeight / (state.range * 2);

    // 使用较小的缩放比例以确保所有内容都能显示
    state.scale = Math.min(scaleByWidth, scaleByHeight);

    // 重置偏移量
    state.offsetX = 0;
    state.offsetY = 0;

    updateGrid();
}

// 渲染目标点
function renderTargets() {
    // 清空现有目标点
    targetsContainer.innerHTML = '';

    Object.values(state.targets).forEach(target => {
        const { xyz, mode, ip } = target;
        const { x, y, z } = xyz;

        // 计算在坐标系中的位置
        const containerRect = coordinateContainer.getBoundingClientRect();
        const centerX = containerRect.width / 2;
        const centerY = containerRect.height / 2;

        // 应用缩放和平移
        const scaledX = centerX + x * state.scale + state.offsetX;
        const scaledY = centerY - y * state.scale + state.offsetY; // Y轴向下为负

        // 获取颜色
        const colorClass = modeColors[mode] || modeColors['default'];
        const isSelected = state.selectedTargets.has(ip);

        // 创建目标点元素
        const targetElement = document.createElement('div');
        targetElement.className = `target-icon ${colorClass} ${isSelected ? 'selected' : ''}`;
        targetElement.style.left = `${scaledX}px`;
        targetElement.style.top = `${scaledY}px`;
        targetElement.innerHTML = `<i class="fa fa-dot-circle-o"></i>`;
        targetElement.title = ip;
        targetElement.dataset.ip = ip;

        // 添加点击事件
        targetElement.style.pointerEvents = 'auto';
        targetElement.addEventListener('click', (e) => {
            e.stopPropagation();
            toggleTargetSelection(ip);
        });

        targetsContainer.appendChild(targetElement);
    });
}

// 切换目标选择状态
function toggleTargetSelection(ip) {
    if (state.selectedTargets.has(ip)) {
        state.selectedTargets.delete(ip);
    } else {
        state.selectedTargets.add(ip);
    }
    renderTargets();
    renderTargetsInfo();
}

// 渲染轨迹线
function renderTrackingLines() {
    // 清空现有轨迹线
    trackingLinesContainer.innerHTML = '';

    if (!state.tracking) return;

    Object.entries(state.tracks).forEach(([ip, points]) => {
        if (points.length < 2) return;

        const target = state.targets[ip];
        if (!target) return;

        // 获取颜色
        const colorClass = modeColors[target.mode] || modeColors['default'];
        const color = colorClass.split('-')[1]; // 提取颜色名称

        // 计算在坐标系中的位置
        const containerRect = coordinateContainer.getBoundingClientRect();
        const centerX = containerRect.width / 2;
        const centerY = containerRect.height / 2;

        for (let i = 0; i < points.length - 1; i++) {
            const p1 = points[i];
            const p2 = points[i + 1];

            // 应用缩放和平移
            const x1 = centerX + p1.x * state.scale + state.offsetX;
            const y1 = centerY - p1.y * state.scale + state.offsetY;
            const x2 = centerX + p2.x * state.scale + state.offsetX;
            const y2 = centerY - p2.y * state.scale + state.offsetY;

            // 计算线段长度和角度
            const dx = x2 - x1;
            const dy = y2 - y1;
            const length = Math.sqrt(dx * dx + dy * dy);
            const angle = Math.atan2(dy, dx) * 180 / Math.PI;

            // 创建线段元素
            const line = document.createElement('div');
            line.className = `tracking-line bg-${color}-500/50`;
            line.style.left = `${x1}px`;
            line.style.top = `${y1}px`;
            line.style.width = `${length}px`;
            line.style.transform = `rotate(${angle}deg)`;

            trackingLinesContainer.appendChild(line);
        }
    });
}

// 渲染目标信息
function renderTargetsInfo() {
    if (Object.keys(state.targets).length === 0) {
        targetsInfo.innerHTML = `
            <div class="text-center text-gray-500 italic">
                暂无目标数据
            </div>
        `;
        return;
    }

    targetsInfo.innerHTML = '';

    Object.values(state.targets).forEach(target => {
        const { ip, mode, rssi, lla, xyz, delay, distance } = target;
        const { longitude, latitude, altitude } = lla;
        const { x, y, z } = xyz;

        // 获取颜色
        const colorClass = modeColors[mode] || modeColors['default'];
        const colorName = colorClass.split('-')[1]; // 提取颜色名称
        const isSelected = state.selectedTargets.has(ip);

        const infoCard = document.createElement('div');
        infoCard.className = `bg-gray-50 p-3 rounded-lg border border-gray-200 hover:border-gray-300 transition-colors duration-200 ${isSelected ? 'border-primary' : ''}`;
        infoCard.innerHTML = `
            <div class="flex justify-between items-start mb-2">
                <h3 class="font-semibold text-gray-800">${ip}</h3>
                <span class="px-2 py-1 rounded-full text-xs font-medium bg-${colorName}-100 text-${colorName}-800">
                    ${mode}
                </span>
            </div>
            <div class="flex items-center mb-2">
                <label class="inline-flex items-center cursor-pointer">
                    <input type="checkbox" class="form-checkbox h-4 w-4 text-primary rounded target-checkbox" data-ip="${ip}" ${isSelected ? 'checked' : ''}>
                    <span class="ml-2 text-sm text-gray-700">选择记录</span>
                </label>
            </div>
            <div class="grid grid-cols-2 gap-2 text-sm">
                <div>
                    <span class="text-gray-500"><i class="fa fa-signal mr-1"></i>信号强度:</span>
                    <span class="font-medium">${rssi.toFixed(2)} dBm</span>
                </div>
                <div>
                    <span class="text-gray-500"><i class="fa fa-clock-o mr-1"></i>延迟:</span>
                    <span class="font-medium">${delay.toFixed(2)} s</span>
                </div>
                <div>
                    <span class="text-gray-500"><i class="fa fa-globe mr-1"></i>经度:</span>
                    <span class="font-medium">${longitude.toFixed(6)}°</span>
                </div>
                <div>
                    <span class="text-gray-500"><i class="fa fa-map-marker mr-1"></i>纬度:</span>
                    <span class="font-medium">${latitude.toFixed(6)}°</span>
                </div>
                <div>
                    <span class="text-gray-500"><i class="fa fa-arrows-v mr-1"></i>高度:</span>
                    <span class="font-medium">${altitude.toFixed(2)} m</span>
                </div>
                <div>
                    <span class="text-gray-500"><i class="fa fa-compass mr-1"></i>动向:</span>
                    <span class="font-medium">${x.toFixed(2)} m</span>
                </div>
                <div>
                    <span class="text-gray-500"><i class="fa fa-compass mr-1"></i>北向:</span>
                    <span class="font-medium">${y.toFixed(2)} m</span>
                </div>
                <div>
                    <span class="text-gray-500"><i class="fa fa-rocket mr-1"></i>天向:</span>
                    <span class="font-medium">${z.toFixed(2)} m</span>
                </div>
                <div>
                    <span class="text-gray-500"><i class="fa fa-arrows-alt mr-1"></i>距离原点:</span>
                    <span class="font-medium">${distance.toFixed(2)} m</span>
                </div>
            </div>
        `;

        // 添加选择事件
        const checkbox = infoCard.querySelector('.target-checkbox');
        checkbox.addEventListener('change', (e) => {
            if (e.target.checked) {
                state.selectedTargets.add(ip);
            } else {
                state.selectedTargets.delete(ip);
            }
            renderTargets();
        });

        targetsInfo.appendChild(infoCard);
    });

    // 更新全选复选框状态
    selectAllCheckbox.checked = Object.keys(state.targets).length > 0 &&
        Object.keys(state.targets).every(ip => state.selectedTargets.has(ip));
}

// 更新网格
function updateGrid() {
    // 由于取消了网格，这里只需要更新原点位置
    renderAxes();
}

// 渲染坐标轴和刻度
function renderAxes() {
    axes.innerHTML = '';

    const containerRect = coordinateContainer.getBoundingClientRect();
    const centerX = containerRect.width / 2;
    const centerY = containerRect.height / 2;

    // X轴
    const xAxis = document.createElement('div');
    xAxis.className = 'axis';
    xAxis.style.width = `${containerRect.width}px`;
    xAxis.style.height = '1px';
    xAxis.style.left = '0';
    xAxis.style.top = `${centerY + state.offsetY}px`;
    axes.appendChild(xAxis);

    // Y轴
    const yAxis = document.createElement('div');
    yAxis.className = 'axis';
    yAxis.style.width = '1px';
    yAxis.style.height = `${containerRect.height}px`;
    yAxis.style.left = `${centerX + state.offsetX}px`;
    yAxis.style.top = '0';
    axes.appendChild(yAxis);

    // X轴标签
    const xLabel = document.createElement('div');
    xLabel.className = 'axis-label';
    xLabel.style.left = `${containerRect.width - 15}px`;
    xLabel.style.top = `${centerY + state.offsetY - 15}px`;
    xLabel.textContent = 'X (东)';
    axes.appendChild(xLabel);

    // Y轴标签
    const yLabel = document.createElement('div');
    yLabel.className = 'axis-label';
    yLabel.style.left = `${centerX + state.offsetX + 5}px`;
    yLabel.style.top = '10px';
    yLabel.textContent = 'Y (北)';
    axes.appendChild(yLabel);

    // 原点图标
    const originIcon = document.createElement('div');
    originIcon.className = 'absolute text-blue-500';
    originIcon.style.left = `${centerX + state.offsetX - 8}px`;
    originIcon.style.top = `${centerY + state.offsetY - 8}px`;
    originIcon.innerHTML = '<i class="fa fa-crosshairs text-lg"></i>';
    axes.appendChild(originIcon);

    // 原点标签
    const originLabel = document.createElement('div');
    originLabel.className = 'axis-label';
    originLabel.style.left = `${centerX + state.offsetX + 15}px`;
    originLabel.style.top = `${centerY + state.offsetY + 5}px`;
    originLabel.textContent = 'O (0,0)';
    axes.appendChild(originLabel);

    // 确定刻度间隔
    let tickInterval;
    if (state.range <= 5) {
        tickInterval = 1; // 1米间隔
    } else if (state.range <= 20) {
        tickInterval = 5; // 5米间隔
    } else if (state.range <= 50) {
        tickInterval = 10; // 10米间隔
    } else {
        tickInterval = 20; // 20米间隔
    }

    // 计算显示的刻度范围
    const visibleRangeX = Math.ceil(containerRect.width / 2 / state.scale);
    const visibleRangeY = Math.ceil(containerRect.height / 2 / state.scale);

    // 添加X轴刻度
    for (let x = -visibleRangeX; x <= visibleRangeX; x += tickInterval) {
        if (x === 0) continue; // 原点已经有标记

        const tickX = centerX + x * state.scale + state.offsetX;

        if (tickX >= 0 && tickX <= containerRect.width) {
            // 创建刻度线
            const tick = document.createElement('div');
            tick.className = 'axis-tick';
            tick.style.left = `${tickX}px`;
            tick.style.top = `${centerY + state.offsetY - 4}px`;
            axes.appendChild(tick);

            // 创建刻度标签
            const label = document.createElement('div');
            label.className = 'axis-tick-label';
            label.style.left = `${tickX - 5}px`;
            label.style.top = `${centerY + state.offsetY + 5}px`;
            label.textContent = `${x}`;
            axes.appendChild(label);
        }
    }

    // 添加Y轴刻度
    for (let y = -visibleRangeY; y <= visibleRangeY; y += tickInterval) {
        if (y === 0) continue; // 原点已经有标记

        const tickY = centerY - y * state.scale + state.offsetY;

        if (tickY >= 0 && tickY <= containerRect.height) {
            // 创建刻度线
            const tick = document.createElement('div');
            tick.className = 'axis-tick-y';
            tick.style.left = `${centerX + state.offsetX - 4}px`;
            tick.style.top = `${tickY}px`;
            axes.appendChild(tick);

            // 创建刻度标签
            const label = document.createElement('div');
            label.className = 'axis-tick-label';
            label.style.left = `${centerX + state.offsetX + 5}px`;
            label.style.top = `${tickY - 5}px`;
            label.textContent = `${y}`;
            axes.appendChild(label);
        }
    }
}

// 绑定事件
function bindEvents() {
    // 范围选择事件
    rangeSelect.addEventListener('change', (e) => {
        const value = e.target.value;
        if (value === 'auto') {
            state.autoRange = true;
            adjustRangeToFitTargets();
        } else {
            state.autoRange = false;
            state.range = parseInt(value);
            calculateScaleFromRange();
        }
        renderTargets();
        renderTrackingLines();
        renderAxes();
    });

    // 开始记录按钮
    startRecordBtn.addEventListener('click', () => {
        state.tracking = !state.tracking;

        if (state.tracking) {
            startRecordBtn.innerHTML = '<i class="fa fa-pause mr-2"></i>停止记录';
            startRecordBtn.classList.remove('bg-primary');
            startRecordBtn.classList.add('bg-red-500');

            // 初始化轨迹数据
            Object.keys(state.targets).forEach(ip => {
                if (!state.tracks[ip]) state.tracks[ip] = [];
            });
        } else {
            startRecordBtn.innerHTML = '<i class="fa fa-play mr-2"></i>开始记录';
            startRecordBtn.classList.remove('bg-red-500');
            startRecordBtn.classList.add('bg-primary');
        }
    });

    // 清空记录按钮
    clearRecordBtn.addEventListener('click', () => {
        state.tracks = {};
        renderTrackingLines();
    });

    // 保存记录按钮
    saveRecordBtn.addEventListener('click', saveTracks);

    // 全选复选框
    selectAllCheckbox.addEventListener('change', (e) => {
        if (e.target.checked) {
            Object.keys(state.targets).forEach(ip => {
                state.selectedTargets.add(ip);
            });
        } else {
            state.selectedTargets.clear();
        }
        renderTargets();
        renderTargetsInfo();
    });

    // 鼠标滚轮缩放
    coordinateContainer.addEventListener('wheel', (e) => {
        e.preventDefault();

        const delta = e.deltaY > 0 ? -0.1 : 0.1;
        const newScale = Math.max(10, Math.min(500, state.scale * (1 + delta))); // 限制缩放范围

        // 计算鼠标位置
        const rect = coordinateContainer.getBoundingClientRect();
        const mouseX = e.clientX - rect.left;
        const mouseY = e.clientY - rect.top;

        // 计算鼠标相对于原点的位置
        const mouseRelativeToOriginX = mouseX - (rect.width / 2 + state.offsetX);
        const mouseRelativeToOriginY = mouseY - (rect.height / 2 + state.offsetY);

        // 应用新缩放比例
        state.scale = newScale;

        // 调整偏移量，使鼠标指向的点保持不变
        state.offsetX = mouseX - (rect.width / 2) - mouseRelativeToOriginX * (state.scale / (state.scale / (1 + delta)));
        state.offsetY = mouseY - (rect.height / 2) - mouseRelativeToOriginY * (state.scale / (state.scale / (1 + delta)));

        updateGrid();
        renderTargets();
        renderTrackingLines();
    });

    // 鼠标拖动
    coordinateContainer.addEventListener('mousedown', (e) => {
        if (e.button !== 0) return; // 只处理左键

        state.isDragging = true;
        state.lastX = e.clientX;
        state.lastY = e.clientY;
        coordinateContainer.style.cursor = 'grabbing';
    });

    document.addEventListener('mousemove', (e) => {
        if (!state.isDragging) return;

        const dx = e.clientX - state.lastX;
        const dy = e.clientY - state.lastY;

        state.offsetX += dx;
        state.offsetY += dy;

        state.lastX = e.clientX;
        state.lastY = e.clientY;

        updateGrid();
        renderTargets();
        renderTrackingLines();
    });

    document.addEventListener('mouseup', () => {
        state.isDragging = false;
        coordinateContainer.style.cursor = 'default';
    });

    // 触摸事件 - 单指拖动
    coordinateContainer.addEventListener('touchstart', (e) => {
        if (e.touches.length === 1) {
            state.isDragging = true;
            state.lastX = e.touches[0].clientX;
            state.lastY = e.touches[0].clientY;
            coordinateContainer.style.cursor = 'grabbing';
        } else if (e.touches.length === 2) {
            // 双指捏合缩放
            state.isPinching = true;
            const touch1 = e.touches[0];
            const touch2 = e.touches[1];

            // 计算两指距离
            const dx = touch2.clientX - touch1.clientX;
            const dy = touch2.clientY - touch1.clientY;
            state.lastDistance = Math.sqrt(dx * dx + dy * dy);

            // 计算捏合中心
            state.pinchCenterX = (touch1.clientX + touch2.clientX) / 2;
            state.pinchCenterY = (touch1.clientY + touch2.clientY) / 2;
        }
    });

    coordinateContainer.addEventListener('touchmove', (e) => {
        e.preventDefault();

        if (state.isDragging && e.touches.length === 1) {
            const touch = e.touches[0];
            const dx = touch.clientX - state.lastX;
            const dy = touch.clientY - state.lastY;

            state.offsetX += dx;
            state.offsetY += dy;

            state.lastX = touch.clientX;
            state.lastY = touch.clientY;

            updateGrid();
            renderTargets();
            renderTrackingLines();
        } else if (state.isPinching && e.touches.length === 2) {
            const touch1 = e.touches[0];
            const touch2 = e.touches[1];

            // 计算两指新距离
            const dx = touch2.clientX - touch1.clientX;
            const dy = touch2.clientY - touch1.clientY;
            const newDistance = Math.sqrt(dx * dx + dy * dy);

            // 计算缩放比例
            const scaleFactor = newDistance / state.lastDistance;
            const newScale = Math.max(10, Math.min(500, state.scale * scaleFactor));

            // 计算捏合中心
            const newPinchCenterX = (touch1.clientX + touch2.clientX) / 2;
            const newPinchCenterY = (touch1.clientY + touch2.clientY) / 2;

            // 计算鼠标相对于原点的位置
            const rect = coordinateContainer.getBoundingClientRect();
            const pinchRelativeToOriginX = state.pinchCenterX - (rect.width / 2 + state.offsetX);
            const pinchRelativeToOriginY = state.pinchCenterY - (rect.height / 2 + state.offsetY);

            // 应用新缩放比例
            state.scale = newScale;

            // 调整偏移量，使捏合中心保持不变
            state.offsetX = state.pinchCenterX - (rect.width / 2) - pinchRelativeToOriginX * state.scale / (state.scale / scaleFactor);
            state.offsetY = state.pinchCenterY - (rect.height / 2) - pinchRelativeToOriginY * state.scale / (state.scale / scaleFactor);

            // 更新捏合状态
            state.lastDistance = newDistance;
            state.pinchCenterX = newPinchCenterX;
            state.pinchCenterY = newPinchCenterY;

            updateGrid();
            renderTargets();
            renderTrackingLines();
        }
    });

    coordinateContainer.addEventListener('touchend', (e) => {
        state.isDragging = false;
        state.isPinching = false;
        coordinateContainer.style.cursor = 'default';
    });

    // 窗口大小变化
    window.addEventListener('resize', () => {
        if (!state.isDragging && !state.isPinching) {
            // 重新计算适合当前窗口大小的缩放比例
            calculateScaleFromRange();
        }
        renderTargets();
        renderTrackingLines();
        renderAxes();
    });
}

// 保存轨迹数据
function saveTracks() {
    const selectedTracks = Array.from(state.selectedTargets);

    if (selectedTracks.length === 0) {
        alert('请先选择要保存的目标');
        return;
    }

    const hasData = selectedTracks.some(ip => state.tracks[ip] && state.tracks[ip].length > 0);

    if (!hasData) {
        alert('选中的目标没有轨迹数据可保存');
        return;
    }

    // 构建CSV内容
    let csvContent = "IP,Timestamp,RSSI,Mode,East(North),North(Y),Up(Z),Longitude,Latitude,Altitude\n";

    selectedTracks.forEach(ip => {
        const points = state.tracks[ip] || [];
        points.forEach(point => {
            const timestamp = new Date(point.timestamp).toISOString();
            const { x, y, z, rssi, mode, lla } = point;
            const { longitude, latitude, altitude } = lla;

            csvContent += `${ip},${timestamp},${rssi.toFixed(2)},${mode},${x.toFixed(2)},${y.toFixed(2)},${z.toFixed(2)},${longitude.toFixed(6)},${latitude.toFixed(6)},${altitude.toFixed(2)}\n`;
        });
    });

    // 创建下载链接
    const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
    const url = URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.setAttribute('href', url);
    link.setAttribute('download', `target_tracks_${new Date().toISOString().slice(0,19).replace(/:/g,'-')}.csv`);
    link.style.visibility = 'hidden';

    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
}

// 启动应用
document.addEventListener('DOMContentLoaded', init);